package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.aliyun.oss.ClientException;
import com.aliyuncs.DefaultAcsClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.exception.BusinessException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备
 */
@Service
@Slf4j
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {
    @Autowired
    private Client client;

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void syncProductList() {
        log.info("===================同步产品列表开始===============");
        int page = 1;
        while (true) {
            //请求参数
            QueryProductListRequest request = new QueryProductListRequest();
            request.setCurrentPage(page++);
            request.setPageSize(20);
            request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            if(page==2){
                redisTemplate.delete("PRODUCT_LIST");
            }
            //调用第三方查询产品列表
            QueryProductListResponse response;
            try {
                response = client.queryProductList(request);
            } catch (Exception e) {
                throw new BusinessException("产品列表查询异常");
            }

            //判断结果，如果数据为空，则跳出循环
            if (!response.getBody().getSuccess() || CollectionUtil.isEmpty(response.getBody().getData().getList().getProductInfo())) {
                return;
            }

            //获取数据，存储到redis
            List<ProductVo> productVoList = response.getBody().getData().getList().getProductInfo().stream().map(
                    p -> BeanUtil.toBean(p, ProductVo.class)
            ).collect(Collectors.toList());

            //存储到redis
            redisTemplate.opsForList().leftPushAll("PRODUCT_LIST", productVoList);
            log.info("===================同步产品列表结束===============");
        }
    }

    @Override
    public List<ProductVo> findAllProduct() {
        return redisTemplate.opsForList().range("PRODUCT_LIST", 0, -1);
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //1. 检查设备名称是否重复, 重复则报错
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getDeviceName,deviceDto.getDeviceName());
        Long count = getBaseMapper().selectCount(wrapper);
        if (count > 0) {
            throw new BusinessException("设备名称已存在,请更换");
        }

        //2. 向IOT新增设备
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response = null;
        try {
            response = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BusinessException("设备注册失败");
        }
        //判断接口是否调通
        if (response == null || !response.getBody().success) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        //3. 准备向数据库保存的数据
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(response.getBody().getData().getIotId());//设备id
        String productName = this.findAllProduct().stream().filter(
                e -> StrUtil.equals(e.getProductKey(), deviceDto.getProductKey())
        ).findFirst().get().getProductName();
        device.setProductName(productName);//产品名称

        //如果设备绑定的位置是随身设备，则把物理绑定位置设置为-1
        if(device.getLocationType() == 0){
            device.setPhysicalLocationType(-1);
        }

        //4. 保存设备数据到数据库
        try {
            getBaseMapper().insert(device);
        }catch (Exception e){
            //保存失败, 则删除iot中的设备数据
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setDeviceName(device.getNickname());
            deleteDeviceRequest.setIotId(device.getIotId());
            deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteDeviceRequest.setProductKey(device.getProductKey());


            try {
                client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                throw new BusinessException("物联网删除设备错误");
            }

            throw new BusinessException("重新选择产品");
        }
    }

    @Override
    public PageResponse<Device> findByPage(DevicePageQueryDto devicePageQueryDto) {
        //1. 设置分页条件
        Page<Device> page = new Page<>(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());
        //2. 设置查询条件
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StrUtil.isNotEmpty(devicePageQueryDto.getProductKey()), Device::getProductKey, devicePageQueryDto.getProductKey())
                .eq(devicePageQueryDto.getLocationType() != null, Device::getLocationType, devicePageQueryDto.getLocationType())
                .like(StrUtil.isNotEmpty(devicePageQueryDto.getDeviceName()), Device::getDeviceName, devicePageQueryDto.getDeviceName())
                .orderByDesc(Device::getCreateTime);

        //3. 执行查询
        page = getBaseMapper().selectPage(page, wrapper);

        //4. 查询创建人
        page.getRecords().stream().forEach(e->e.setCreator("超级管理员"));

        return new PageResponse<>(page);
    }

    @Override
    public DeviceVo queryDeviceDetail(QueryDeviceDetailRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse response;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new BusinessException("物联网查询设备错误");
        }
        //判断接口是否调通
        if (!response.getBody().getSuccess()) {
            throw new BusinessException("物联网查询设备错误");
        }

        //查询数据库的数据
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getIotId, request.getIotId());
        Device device = getBaseMapper().selectOne(wrapper);
        DeviceVo deviceVo = BeanUtil.copyProperties(device, DeviceVo.class);

        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
        BeanUtil.copyProperties(data, deviceVo, CopyOptions.create().ignoreNullValue());

        return deviceVo;
    }
@Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(DeviceDto deviceDto) {

        LambdaQueryWrapper<Device> deviceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deviceLambdaQueryWrapper.eq(Device::getIotId, deviceDto.getIotId());
        if (getBaseMapper().delete(deviceLambdaQueryWrapper) <= 0) {
            throw new BusinessException("删除失败");
        }
        DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
        deleteDeviceRequest.setDeviceName(deviceDto.getDeviceName());
        deleteDeviceRequest.setIotId(deviceDto.getIotId());
        deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            client.deleteDevice(deleteDeviceRequest);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("物联网删除设备错误");
        }
    }

    @Override
    public void updateDevice(DeviceDto deviceDto) {
        // 1.先将DeviceDto转换为Device对象
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        // 2.通过productKey查询产品名称
        String productName = this.findAllProduct().stream().filter(
                e -> StrUtil.equals(e.getProductKey(), deviceDto.getProductKey())
        ).findFirst().get().getProductName();
        if(StrUtil.isNotEmpty(productName)){
            device.setProductName(productName);
        }
        // 3.通过Id查询设备名称iotId
        Device device_db = getBaseMapper().selectById(deviceDto.getId());
        if(BeanUtil.isNotEmpty(device_db)){
            device.setIotId(device_db.getIotId());
        }
        // 4.更新数据库数据
        if(getBaseMapper().updateById(device) <= 0){
            throw new BusinessException("更新失败");
        }
        if(device.getLocationType() == 0){
            device.setPhysicalLocationType(-1);
        }
//        // 5.更新物联网平台数据
//        UpdateDeviceShadowRequest request = new UpdateDeviceShadowRequest();
//        request.setProductKey(deviceDto.getProductKey());
//        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
//        request.setDeviceName(deviceDto.getDeviceName());
//        try {
//            client.updateDeviceShadow(request);
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new BusinessException("物联网更新设备错误");
//        }
    }


}
